using System;
using Microsoft.SPOT;
using Gadgeteer.Interfaces.Led;
using System.Collections;
using System.Text;
using Gadgeteer.Interfaces;

namespace Gadgeteer.Interfaces.Sample.Safe.SafeApp
{
    public class CombinationEntering
    {
        private IButton[] btns;
        private Lock padlock;
        private ITimer nodsReset;
        private ITimer closeLock;
        private ArrayList nodsSet;
        private ILogger logger;

        public bool IsOpen
        {
            get { return padlock.IsOpen; }
        }

        /// <summary>
        /// Supply a lock to open and a set of buttons that simulate the code.
        /// </summary>
        public CombinationEntering(Lock padLock, params IButton[] nobs)
        {
            padlock = padLock;
            this.btns = nobs;
            this.logger = ServiceLocator.Locator.Logger;
            nodsSet = new ArrayList();

            for (int i = 0; i < nobs.Length; i++)
            {
                nobs[i].ButtonPressed += LockKeeper_ButtonPressed;
            }

            // We want to reset the combination after 2 seconds so you can try different combinations.
            nodsReset = ServiceLocator.Factories.Timer.Create(2000);
            nodsReset.Tick += nodsReset_Tick;

            // We want to close the door if it has been unattended for a while.
            closeLock = ServiceLocator.Factories.Timer.Create(5000);
            closeLock.Tick += closeLock_Tick;

            nodsReset.Start();
            closeLock.Start();
        }

        /// <summary>
        /// Close the door because it has been open for a while, to prevent this press any button.
        /// </summary>
        void closeLock_Tick(ITimer timer)
        {
            logger.Print("Close door");
            padlock.Close();
        }

        private void AttemptOpen()
        {
            var currentCode = GetCurrentCode();
            var text = new StringBuilder();
            text.Append("Attempt opening with");
            for(int i = 0; i < currentCode.Length; i++)
            {
                text.Append(" ");
                text.Append(currentCode[i]);
            }
            logger.Print(text.ToString());
            closeLock.Restart();
            if (padlock.OpenWithCode(currentCode))
            {
                logger.Print("Door opened");
                closeLock.Restart();
            }
        }

        public int[] GetCurrentCode()
        {
            int[] currentCode = new int[nodsSet.Count];
            for (int i = 0; i < currentCode.Length; i++)
            {
                currentCode[i] = (int)nodsSet[i];
            }
            return currentCode;
        }

        void LockKeeper_ButtonPressed(IButton sender, ButtonState state)
        {
            if (padlock.IsOpen)
            {
                logger.Print("Keep the door open...");
                closeLock.Restart();
            }
            else
            {
                for (int i = 0; i < btns.Length; i++)
                {
                    if (btns[i] == sender)
                    {
                        logger.Print("Button[" + i + "] pressed.");
                        nodsSet.Add(i);
                        nodsReset.Restart();
                    }
                }
                AttemptOpen();
            }
        }

        void nodsReset_Tick(ITimer timer)
        {
            logger.Print("Timed out, clearing combination");
            nodsSet.Clear();
        }
    }
}
